<?php

/**
 * Description of Utilizador
 * Utilizador da aplicação
 * 
 * @author lmcosta
 */
class Utilizador {

    var $id;
    var $username;
    var $password;

    function __construct($id, $username, $password) {
        $this->id = $id;
        $this->username = $username;
        $this->password = $password;
    }

    public function __toString() {
        return $this->username;
    }

}

/**
 * Description of UtilizadorDB
 *
 * @author lmcosta
 */
class UtilizadorDB {

    var $db_table;
    var $msg_erro;

    function __construct() {
        //Dados por defeito
        $this->db_table = "utilizadores";
        $this->msg_erro = "";
    }
    
    /**
     * Obter utilizador da base de dados pelo seu ID
     * @param type $id
     * @return boolean|\Utilizador 
     */
    public function getUtilizador($id) {
        $site = Site::getInstance();
        if (!$site->ligarDB($this->msg_erro)) {
            return false;
        }
        
        //Manter segurança para não causar sql injection
        $id = FormHelper::tranformarToQuery($id);
        
        $sql = "SELECT * FROM `$this->db_table` WHERE `id` = $id LIMIT 1 ";
        $result = mysql_query($sql, $site->ligacao_db);
        
        if (!$result || mysql_num_rows($result) <= 0) {
            $this->msg_erro = "Este utilizador não existe na base de dados!";
            return false;
        }
        
        $user = mysql_fetch_object( $result );
        
        $utilizador = new Utilizador($user->id, $user->username, $user->password);
        
        mysql_free_result($result);
        $site->closeDB();

        return $utilizador;
    }
    
    /**
     * Obter utilziador da base dados pelo seu username
     * @param type $username
     * @return boolean|\Utilizador 
     */
    public function getUtilizadorByName($username) {
        $site = Site::getInstance();
        if (!$site->ligarDB($this->msg_erro)) {
            return false;
        }

        //Manter segurança para não causar sql injection
        $username = FormHelper::tranformarToQuery($username);
        
        $sql = "SELECT * FROM `$this->db_table` WHERE `username` = '{$username}' LIMIT 1 ";
        $result = mysql_query($sql, $site->ligacao_db);
        
        if (!$result || mysql_num_rows($result) <= 0) {
            $this->msg_erro = "Não existe na base de dados!";
            return false;
        }

        $user = mysql_fetch_object( $result );
        
        $utilizador = new Utilizador($user->id, $user->username, $user->password);
        
        mysql_free_result($result);
        $site->closeDB();

        return $utilizador;
    }
    
    /**
     * Obter todos os utilizadores da base dados
     * @return boolean|\Utilizador 
     */
    public function getAllUtilizadores() {
        $site = Site::getInstance();
        if (!$site->ligarDB($this->msg_erro)) {
            return false;
        }

        $sql = "SELECT * FROM `$this->db_table` ";
        $result = mysql_query($sql, $site->ligacao_db);

        $utilizadores = array();
        while ($user = mysql_fetch_object($result)) {
            $utilizadores[] = new Utilizador($user->id, $user->username, $user->password);
        }
        mysql_free_result($result);
        $site->closeDB();

        return $utilizadores;
    }

    /**
     * Adicionar um utilizador à base de dados
     * @param Utilizador $utilizador
     * @return boolean 
     */
    public function adicionarUtilizador(Utilizador $utilizador) {
        $site = Site::getInstance();
        if (!$site->ligarDB($this->msg_erro)) {
            return false;
        }

        //Manter segurança para não causar sql injection
        $utilizador->username = FormHelper::tranformarToQuery($utilizador->username);
        $utilizador->password = FormHelper::tranformarToQuery($utilizador->password);
        
        $sql = "INSERT INTO `$this->db_table` (`username`, `password`) ";
        $sql .= "VALUES (
                    '{$utilizador->username}',
                    '{$utilizador->password}');";

        if (!mysql_query($sql, $site->ligacao_db)) {
            $this->msg_erro = "Erro ao inserir o utilizador na base de dados!\r\n";
            return false;
        }

        return true;
    }
    
    /**
     * Actualziar a password de um utilizador na base de dados
     * @param Utilizador $utilizador
     * @return boolean 
     */
    public function editarUtilizador(Utilizador $utilizador) {
        $site = Site::getInstance();
        if (!$site->ligarDB($this->msg_erro)) {
            return false;
        }

        //Manter segurança para não causar sql injection
        $utilizador->id = FormHelper::tranformarToQuery($utilizador->id);
        $utilizador->password = FormHelper::tranformarToQuery($utilizador->password);
        
        $sql = "UPDATE `$this->db_table` SET `password` = '{$utilizador->password}' WHERE `id` = '{$utilizador->id}' ";
        if (!mysql_query($sql, $site->ligacao_db)) {
            $this->msg_erro = "Erro ao editar o utilizador na base de dados!\r\n";
            return false;
        }

        return true;
    }
}

/**
 * Classe para utilizar no formulário de novo utilizador 
 */
class UtilizadorForm {

    var $id;
    var $username;
    var $password;
    var $csrf_token;
    var $msg_erro;

    /**
     * Cria um novo objecto que representa o formulário de adicionar utilizador.
     * Retira os espaços e efectua o Encode para evitar ataques XSS 
     */
    function __construct() {
        $this->id = trim(FormHelper::encodeInput('id'));
        $this->username = trim(FormHelper::encodeInput('username'));
        $this->password = trim(FormHelper::encodeInput('password'));
        $this->csrf_token = trim(FormHelper::encodeInput('csrf_token'));
    }

    /**
     * Validar dados do formulário de inserção de novo utilizador
     * @return boolean 
     */
    public function validaUtilizador() {

        //Validar se a csrf_token é igual à que foi gerada quando foi apresentado o formulário
        if ($this->csrf_token != $_SESSION['csrf_token']) {
            $this->defineErro("Iniciar de novo o formulário!");
            return false;
        }
        
        //Validar username
        if (!FormHelper::validateUsername($this->username, 4, 15)) {
            $this->defineErro("Utilizador inválido. O Utilizador deve conter no minimo 4 e no máximo 15 caracteres. (a-z, A-Z, 0-9, _ )");
            return false;
        }
        
        //Validar password
        if (!FormHelper::validatePassword($this->password, 4, 15)) {
            $this->defineErro("Password inválida. A password deve conter no minimo 4 e no máximo 15 caracteres. (a-z, A-Z, 0-9, _ )");
            return false;
        }
        
        //Encriptar a password
        $this->password = FormHelper::encriptarPassword($this->password);
        
        $utilizador = new Utilizador($this->id, $this->username, $this->password);

        //Adicionar novo utilizador na base de dados
        $utilizadorDB = new UtilizadorDB();
        $result = $utilizadorDB->adicionarUtilizador($utilizador);
        $this->msg_erro = $utilizadorDB->msg_erro;

        return $result;
    }

    function defineErro($erro) {
        $this->msg_erro .= $erro . "\r\n";
    }

}

/**
 * Alterar Password 
 */
class AlterarPasswordForm {

    var $id;
    var $username;
    var $passwordActual;
    var $passwordNova;
    var $csrf_token;
    var $msg_erro;

    /**
     * Cria um novo objecto que representa o formulário de editar password.
     * Efectua o Encode para evitar ataques XSS 
     */
    function __construct() {
        $this->id = FormHelper::encodeInput('id');
        $this->username = FormHelper::encodeInput('username');
        $this->passwordActual = FormHelper::encodeInput('password1');
        $this->passwordNova = FormHelper::encodeInput('password2');
        $this->csrf_token = FormHelper::encodeInput('csrf_token');
    }

    /**
     * Validar o formulário de alterar a password do utilizador ligado
     * @return boolean 
     */
    public function validaPasswordActual() {

        //Validar se a csrf_token é igual à que foi gerada quando foi apresentado o formulário
        if ($this->csrf_token != $_SESSION['csrf_token']) {
            $this->defineErro("Iniciar de novo o formulário!");
            return false;
        }
        
        //Validar password actual
        if (!FormHelper::validatePassword($this->passwordActual, 4, 15)) {
            $this->defineErro("Password actual inválida. A password deve conter no minimo 4 e no máximo 15 caracteres. (a-z, A-Z, 0-9, _ )");
            return false;
        }
        
        //validar nova password
        if (!FormHelper::validatePassword($this->passwordNova, 4, 15)) {
            $this->defineErro("Password nova inválida. A password deve conter no minimo 4 e no máximo 15 caracteres. (a-z, A-Z, 0-9, _ )");
            return false;
        }
        
        //id do utilizador ligado
        $this->id = $_SESSION['userdata']['id'];
        
        //Obter dados do utilizador actual
        $utilizadorDB = new UtilizadorDB();
        $utilizador = $utilizadorDB->getUtilizador($this->id);
        if($utilizador == false) {
            $this->defineErro($utilizadorDB->msg_erro);
            return false;
        }
        
        //Comparar password actual com a password armazenada na base de dados
        $this->passwordActual = FormHelper::encriptarPassword($this->passwordActual);
        if($this->passwordActual != $utilizador->password) {
            $this->defineErro("A password actual não corresponde a este utilizador!");
            return false;
        }
        
        //Encriptar a nova password e editar na base de dados
        $this->passwordNova = FormHelper::encriptarPassword($this->passwordNova);
        $utilizador->password = $this->passwordNova;
        if(!$utilizadorDB->editarUtilizador($utilizador)) {
            $this->defineErro($utilizadorDB->msg_erro);
            return false;
        }
                
        $this->defineErro("Password alterada com sucesso!");
        return true;
    }
    
    /**
     * Validar o formulário de alterar a password de outro utilizador pelo seu login
     * @return boolean 
     */
    public function validaPasswordOutro() {

        //Validar se a csrf_token é igual à que foi gerada quando foi apresentado o formulário
        if ($this->csrf_token != $_SESSION['csrf_token']) {
            $this->defineErro("Iniciar de novo o formulário!");
            return false;
        }
        
        //validar username
        if (!FormHelper::validateUsername($this->username, 4, 15)) {
            $this->defineErro("Utilizador inválido. O Utilizador deve conter no minimo 4 e no máximo 15 caracteres. (a-z, A-Z, 0-9, _ )");
            return false;
        }
        
        //validar password
        if (!FormHelper::validatePassword($this->passwordActual, 4, 15)) {
            $this->defineErro("Password actual inválida. A password deve conter no minimo 4 e no máximo 15 caracteres. (a-z, A-Z, 0-9, _ )");
            return false;
        }
        
        //validar nova password
        if (!FormHelper::validatePassword($this->passwordNova, 4, 15)) {
            $this->defineErro("Password nova inválida. A password deve conter no minimo 4 e no máximo 15 caracteres. (a-z, A-Z, 0-9, _ )");
            return false;
        }
        
        //Obter utilizador da base de dados pelo seu username
        $utilizadorDB = new UtilizadorDB();
        $utilizador = $utilizadorDB->getUtilizadorByName($this->username);
        if($utilizador == false) {
            $this->defineErro("Username: " .$this->username . " <br />" .$utilizadorDB->msg_erro);
            return false;
        }
        
        //Comparar as passowrds se são iguais
        $this->passwordActual = FormHelper::encriptarPassword($this->passwordActual);
        if($this->passwordActual != $utilizador->password) {
            $this->defineErro("A password não corresponde a este utilizador!");
            return false;
        }
        
        //Encriptar a nova password e guardar na base de dados
        $this->passwordNova = FormHelper::encriptarPassword($this->passwordNova);
        $utilizador->password = $this->passwordNova;
        if(!$utilizadorDB->editarUtilizador($utilizador)) {
            $this->defineErro($utilizadorDB->msg_erro);
            return false;
        }
                
        $this->defineErro("Password alterada com sucesso!");
        return true;
    }

    function defineErro($erro) {
        $this->msg_erro .= $erro . "\r\n";
    }

}
?>
